/*
 *	FileMgr.cpp is part of Flight_Chess_Portable
 *	Copyright (C) 2008  Poison
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 *	Class:			FileMgr
 *	Description:	
 *	Author:			Poison <hbpoison@gmail.com>
 *	Date Created:	2008-02-22
 */

#include "FileMgr.h"

#include <pspiofilemgr.h>

#include <cstring>

IoEntry::IoEntry()
{
	handler = -1;
	path = NULL;
}

IoEntry::~IoEntry()
{
	if ( path )
		delete path;
}

template <class T>
void IoEntry::setPath( T entry_path )
{
	if ( path )
		delete path;
	path = new string ( entry_path );
}

template <class T>
File::File( T entry_path, int mode )
{
	type = T_FILE;
	open( entry_path, mode );
}

File::~File()
{
	if ( handler >= 0 )
		close();
}

int File::open( int mode )
{
	if ( path )
	{
		handler = sceIoOpen( path->c_str(), mode, 0777 );
		if ( handler >= 0 )
			return 0;
	}
	return -1;
}

template <class T>
int File::open( T entry_path, int mode )
{
	setPath( entry_path );
	return open( mode );
}

int File::reopen( int mode )
{
	if ( handler >= 0 )
	{
		close();
		return open( mode );
	}
	return -1;
}

int File::close()
{
	if ( handler >= 0 )
		return sceIoClose( handler );
	return -1;
}

int File::read( void * data, unsigned int size )
{
	if ( handler >= 0 )
		return sceIoRead( handler, data, size );
	return -1;
}

int File::write( void * data, unsigned int size )
{
	if ( handler >= 0 )
		return sceIoWrite( handler, data, size );
	return -1;
}

int File::seek( int pos, FileSeekMode mode = FS_CUR )
{
	if ( handler >= 0 )
		return sceIoLseek( handler, pos, mode );
	return -1;
}

int File::getSize()
{
	if ( handler >= 0 )
	{
		SceIoStat stat;
		memset( &stat, 0, sizeof( SceIoStat ) );
		int ret = sceIoGetstat( path->c_str(), &stat );
		if ( ret >= 0 )
			return stat.st_size;
	}
	return -1;
}

int File::getOffset()
{
	if ( handler >= 0 )
		return sceIoLseek( handler, 0, FS_CUR );
	return -1;
}

template <class T>
Dir::Dir( T entry_path, int mode )
{
	type = T_DIR;
	entry_offset = 0;
	open( entry_path, mode );
}

Dir::~Dir()
{
	if ( handler >= 0 )
		close();
}

int Dir::open( int mode )
{
	if ( path )
	{
		if ( mode == DO_CREATE )
			sceIoMkdir( path->c_str(), 0777 );
		handler = sceIoDopen( path->c_str() );
		if ( handler >= 0 )
			return 0;
	}
	return -1;
}

template <class T>
int Dir::open( T entry_path, int mode )
{
	setPath( entry_path );
	return open( mode );
}

int Dir::reopen( int mode )
{
	if ( handler >= 0 )
	{
		close();
		return open( mode );
	}
	return -1;
}

int Dir::close()
{
	if ( handler >= 0 )
		return sceIoDclose( handler );
	return -1;
}

IoEntry * Dir::nextEntry()
{
	if ( handler >= 0 )
	{
		SceIoDirent ent;
		memset( &ent, 0, sizeof(SceIoDirent) );
		int ret = sceIoDread( handler, &ent );
		if ( ret >= 0)
		{
			entry_offset ++;
			string * ent_path = new string( *path );
			if ( ent_path->at( ent_path->length() - 1 ) != '/' )
				ent_path->append( "/" );
			ent_path->append( ent.d_name );
			if ( ent.d_stat.st_attr & FIO_SO_IFDIR )
			{
				Dir * dir_ent = new Dir( *ent_path );
				delete ent_path;
				return dir_ent;
			}
			else
			{
				File * file_ent = new File( *ent_path );
				delete ent_path;
				return file_ent;
			}
		}
	}
	return NULL;
}

int Dir::getEntryCount()
{
	if ( path )
	{
		int ret = sceIoDopen( path->c_str() );
		if ( ret >= 0 )
		{
			int count = 0;
			SceIoDirent ent;
			memset( &ent, 0, sizeof(SceIoDirent) );
			while ( sceIoDread( ret, &ent ) >= 0 )
				count ++;
			sceIoDclose( ret );
			return count;
		}
	}
	return -1;
}
